package com.xg.te.strategy;

import java.io.StringReader;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jarveis.frame.lang.StringUtil;
import com.xg.te.core.PageStore;
import com.xg.te.core.ParamStore;
import com.xg.te.core.WebsiteStore;
import com.xg.te.core.bean.PageBean;
import com.xg.te.core.bean.WebsiteBean;
import com.xg.te.plugin.Plugin;
import com.xg.te.plugin.PluginProxy;
import com.xg.te.plugin.PluginStore;
import com.xg.te.plugin.bean.PluginBean;
import com.xg.te.plugin.bean.PluginReference;
import com.xg.te.util.FreemarkerUtil;
import com.xg.te.util.ReflectionUtils;

/**
 * @desc 生成策略接口
 * @author liuguojun
 * @date 2014-07-16
 */
public abstract class Strategy {

	protected Logger logger = Logger.getLogger(getClass());

	protected Set<String> pages = new HashSet<String>();

	/**
	 * 执行策略
	 * 
	 * @param jsonObj
	 *            参数对象
	 */
	public abstract void execute(JSONObject jsonObj);

	/**
	 * 添加页面
	 * 
	 * @param page
	 *            页面对象
	 */
	public void addPage(String page) {
		this.pages.add(page);
	}

	/**
	 * 添加页面集合
	 * 
	 * @param pages
	 *            页面集合
	 */
	public void addPages(Collection<String> pages) {
		this.pages.addAll(pages);
	}

	/**
	 * 静态化Html
	 * 
	 * @param websitetCode
	 *            网站编码
	 * @param pageCode
	 *            页面编码
	 * @throws Exception
	 */
	protected void staticHtml(String websitetCode, String pageCode)
			throws Exception {
		this.staticHtml(websitetCode, pageCode, null);
	}

	/**
	 * 静态化Html
	 * 
	 * @param websitetCode
	 *            网站编码
	 * @param pageCode
	 *            页面编码
	 * @param args
	 *            参数
	 * @throws Exception
	 */
	protected void staticHtml(String websitetCode, String pageCode, Map<String, Object> args)
			throws Exception {
		try {
			WebsiteBean website = WebsiteStore.get(websitetCode);

			PageBean page = PageStore.get(pageCode);
			String tpath = page.getTpath();
			String hpath = page.getHpath();
			if (hpath == null) {
				hpath = "";
			}

			/* 页面所需的参数集合 */
			Map<String, Object> params = new HashMap<String, Object>();
			if (page.getPlugins() != null) {
				params = executePlugin(page.getPlugins(), args);
				/* 防止数据异常导致的页面有误 */
				if (params == null) {
					return;
				}
			}
			params.putAll(ParamStore.toMap());

			/* 重置文件路径 */
			if (hpath.indexOf("{") > -1) {
				logger.info("before path = " + hpath);
				hpath = rePath(hpath, params);
				logger.info("after path = " + hpath);
			}

			String tempPath = website.getConstantValue("tempPath");
			String pagePath = website.getConstantValue("pagePath");

			FreemarkerUtil
					.createHtml(tempPath, tpath, pagePath + hpath, params);
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
		}
	}

	/**
	 * 执行插件
	 * 
	 * @param plugins
	 *            插件列表
	 * @return Map<String, Object> 数据集合
	 */
	protected Map<String, Object> executePlugin(List<PluginReference> plugins,
			Map<String, Object> params) {
		Map<String, Object> reMap = new HashMap<String, Object>(1);
		Iterator<PluginReference> it = plugins.iterator();
		while (it.hasNext()) {
			PluginReference ref = it.next();
			String code = ref.getCode();
			String name = ref.getName();

			PluginBean pb = PluginStore.get(code);
			String bean = pb.getBean();
			String args = pb.getArgs();

			// 实例化插件
			Object plugin = null;
			if ("spring".equals(pb.getInit())) {
				// plugin = SpringUtils.getBean(bean);
			} else if ("instance".equals(pb.getInit())) {
				plugin = ReflectionUtils.newInstance(bean);
			}

			// 验证插件是否实例化
			if (plugin == null) {
				logger.info("plugin(code=" + code + ", bean=" + bean
						+ ")不能正常实例化");
				continue;
			}

			// 验证是否是插件
			if (!(plugin instanceof Plugin)) {
				logger.info("plugin(code=" + code + ", bean=" + bean + ")未实现 "
						+ Plugin.class.getName() + " 接口");
				continue;
			}

			// 设置参数
			JSONObject jsonObj = null;
			if (!StringUtil.isEmpty(args)) {
				jsonObj = JSON.parseObject(args);
				if (params != null) {
					jsonObj.putAll(params);
				}
			}

			Map value = PluginProxy.proxyExecute((Plugin) plugin, jsonObj);
			// 验证必需数据是否存在
			if (value.isEmpty() && ref.isMust()) {
				reMap = null;
				break;
			}
			reMap.put(name, value);
		}

		return reMap;
	}

	/**
	 * 重置路径
	 * 
	 * @param path
	 *            源带参数的路径
	 * @param params
	 *            参数集合
	 * @return String 真实路径
	 */
	private String rePath(String path, Map<String, Object> params) {
		StringBuffer buf = new StringBuffer();
		StringBuffer token = new StringBuffer();
		boolean isToken = false;

		StringReader sr = new StringReader(path);
		int i;
		char c;
		Object obj = null;
		try {
			while ((i = sr.read()) != -1) {
				c = (char) i;

				// 判断边界符
				if (c == '{') {
					isToken = true;
					continue;
				} else if (c == '}') {

					if (obj != null) {
						if (obj instanceof Map) {
							String v = (String) ((Map) obj).get(token
									.toString());
							buf.append(v);
						}
					}

					token = token.delete(0, token.length());
					isToken = false;
					continue;
				}

				if (isToken) {
					if (c == '.') {
						if (token.length() > 0) {
							obj = params.get(token.toString());
							token = token.delete(0, token.length());
						}
					} else {
						token.append(c);
					}
				} else {
					buf.append(c);
				}
			}
		} catch (Exception ex) {
			logger.error("路径格式有误(" + path + ")", ex);
		}

		return buf.toString();
	}

}
